import yaml
import json
import re
import random
import string
import uuid
import psutil
import sys


class Util(object):
    def __init__(self):
        self.params_path = []

    @staticmethod
    def read_yaml_config(file_path):
        with open(file_path, 'r', encoding='utf-8') as f:
            cfg = yaml.load(f.read(), Loader=yaml.FullLoader)
            return cfg

    def get_params_path(self, request, data_struct_link, param):
        if isinstance(request, dict):
            keys_list = request.keys()
            for key in keys_list:
                temp_data_struct_link = data_struct_link + f"['{key}']"
                if not isinstance(request[key], list) and not isinstance(request[key], dict):
                    if request[key] == param:
                        self.params_path.append({'path': data_struct_link, 'key': key, 'value': param})
                else:
                    self.get_params_path(request[key], temp_data_struct_link, param)
        elif isinstance(request, list):
            length = len(request)
            for index in range(0, length):
                temp_request = request[index]
                keys_list = temp_request.keys()
                for key in keys_list:
                    temp_data_struct_link = data_struct_link + f"[{index}]['{key}']"
                    if not isinstance(temp_request[key], dict) and not isinstance(temp_request[key], list):
                        # if temp_request[key] == param:
                        self.params_path.append({'path': data_struct_link + f"[{index}]", 'key': key})
                    else:
                        self.get_params_path(temp_request[key], temp_data_struct_link, param)

    def get_request_params_path(self, request):
        data_struct_link = 'request'
        params = re.findall('\\${+\\w+}', json.dumps(request)) + re.findall('\\${+\\w+[(]+\\d+[)]+}',
                                                                            json.dumps(request))
        for param in params:
            self.get_params_path(request, data_struct_link, param)
        return self.params_path

    @staticmethod
    def str_assert(str_obj, another):
        try:
            assert str(str_obj) == str(another)
        except AssertionError:
            raise AssertionError(f'{str_obj} != {another}')

    @staticmethod
    def generate_string(length):
        str_list = random.sample(string.digits + string.ascii_letters, int(length))
        random_str = ''.join(str_list)
        return random_str

    @staticmethod
    def generate_uuid():
        return str(uuid.uuid1())

    @staticmethod
    def kill_process_with_name():
        """根据进程名杀死进程
        """
        process_name = ''
        if sys.platform == 'win32':
            process_name = 'locust.exe'
        elif sys.platform == 'linux':
            process_name = 'locust'
        pid_list = psutil.pids()
        for pid in pid_list:
            try:
                each_pro = psutil.Process(pid)
                if process_name.lower() in each_pro.name().lower():
                    each_pro.terminate()
                    each_pro.wait(timeout=3)
            except psutil.NoSuchProcess:
                pass

    @staticmethod
    def get_locust_process_status():
        process_name = 'locust.exe' if sys.platform == 'win32' else 'locust'
        pl = psutil.pids()
        for pid in pl:
            try:
                each_process = psutil.Process(pid)
                name = each_process.name()
                if process_name.lower() == name.lower():
                    return True
            except psutil.NoSuchProcess:
                return False
